<template>
  <div class="canvasMain" v-loading="loading" id="canvasMainId" @dblclick="domMouseTwoClicked">
    <!-- 知识操作对话栏 -->
    <div id="nodeDialogId" class="nodeDialog">
      <div class="logined">
        <button v-if="!isCollected()" @click="collect()">收藏节点</button>
        <button v-else class="notButton">节点已收藏</button>
      </div>
      <div class="power" v-if="isPower()">
        <el-popover placement="top" :width="160" ref="popoverNode">
          <p>该操作会永久删除节点,您确定吗?</p>
          <div style="text-align: right; margin: 0">
            <el-button size="mini" type="text" @click="popoverNodeClose()">取消</el-button>
            <el-button type="primary" size="mini" @click="deleteNodeClick()">确定</el-button>
          </div>
          <template #reference>
            <button>删除节点</button>
          </template>
        </el-popover>
        <button @click="relative()">节点连接</button>
        <button @click="showEditNodeDialog()">编辑节点</button>
      </div>
      <button @click="nodeTags()">节点简介</button>
      <button @click="cancel()">取消</button>
    </div>

    <!-- 知识联系操作对话栏 -->
    <div id="linkDialogId" class="linkDialog">
      <el-popover placement="top" :width="160" ref="popoverLink">
        <p>该操作会永久删除连线,您确定吗?</p>
        <div style="text-align: right; margin: 0">
          <el-button size="mini" type="text" @click="popoverLinkClose()">取消</el-button>
          <el-button type="primary" size="mini" @click="deleteLinkClick()">确定</el-button>
        </div>
        <template #reference>
          <button>删除连线</button>
        </template>
      </el-popover>
      <button @click="cancelLink()">取消</button>
    </div>

    <!-- 知识修改操作对话栏 -->
    <el-dialog title="修改知识节点" :visible.sync="editNodeDialog" width="50%" :close-on-click-modal="false">
      <el-form :model="editNode" label-width="140px">
        <el-form-item label="所属类别">
          <el-select v-model="editNode.classId" placeholder="请选择所属类别">
            <el-option :label="item.className" :value="item.id" v-for="item in categories" :key="item.id"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="知识名称">
          <el-input v-model="editNode.knowledgeName"></el-input>
        </el-form-item>
        <el-form-item label="标签集(用|分开)">
          <el-input v-model="editNode.knowledgeTag"></el-input>
        </el-form-item>
        <el-form-item label="大小">
          <el-input v-model="editNode.size"></el-input>
        </el-form-item>
        <el-form-item label="知识内容">
          <el-input v-model="editNode.knowledgeContent" type="textarea" :rows="3"></el-input>
        </el-form-item>
        <el-form-item label="颜色(rgb)">
          <el-color-picker v-model="editNode.color" :color-format="'rgb'" :show-alpha="false"></el-color-picker>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="editNodeDialog = false">取 消</el-button>
          <el-button type="primary" @click="editNoded ()">确 定</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 添加知识按钮和知识类别下拉菜单 -->
    <div class="addNode">
      <el-button v-if="isPower()" type="primary" icon="el-icon-plus" circle @click="addNodeDialog = true" size="mini"></el-button>
      <el-dropdown @command="handleCommand" size="mini" placement="top">
        <el-button type="primary" circle icon="el-icon-arrow-down" size="mini"></el-button>
        <template #dropdown>
          <el-dropdown-menu>
            <el-dropdown-item command="0">ALL</el-dropdown-item>
            <el-dropdown-item :command="cate.id" v-for="cate in categories" :key="cate.id">{{cate.className}}</el-dropdown-item>
          </el-dropdown-menu>
        </template>
      </el-dropdown>
    </div>

    <!-- 添加知识对话框 -->
    <el-dialog title="添加知识节点" :visible.sync="addNodeDialog" width="50%" @close="addDialogClose()" :close-on-click-modal="false">
      <el-form :model="addNodeForm" label-width="140px">
        <el-form-item label="所属类别">
          <el-select v-model="addNodeForm.classId" placeholder="请选择所属类别">
            <el-option :label="item.className" :value="item.id" v-for="item in categories" :key="item.id"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="知识名称">
          <el-input v-model="addNodeForm.knowledgeName"></el-input>
        </el-form-item>
        <el-form-item label="大小">
          <el-input v-model="addNodeForm.size"></el-input>
        </el-form-item>
        <el-form-item label="颜色(rgb)">
          <el-color-picker v-model="addNodeForm.color" :color-format="'rgb'" :show-alpha="false"></el-color-picker>
        </el-form-item>
        <el-form-item label="知识内容">
          <el-input v-model="addNodeForm.knowledgeContent" type="textarea" :rows="3"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="addNodeDialog = false">取 消</el-button>
          <el-button type="primary" @click="addNode ()">确 定</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 知识详细信息 -->
    <el-dialog :title="nodeInfo.label" :visible.sync="nodeContentDialog" width="50%" :close-on-click-modal="false">
      <div class="content">{{nodeInfo.properties.knowledgeContent}}</div>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="nodeContentDialog = false">关闭</el-button>
        </span>
      </template>
    </el-dialog>

  </div>
</template>

<script>
    import VisGraph from '@/assets/js/visgraph.min.js'
    import LayoutFactory from '@/assets/js/visgraph-layout.min.js'
    import { config } from '@/assets/canvasConfig.js'
    import { listNode,listAllNode, getNode, delNode, addNode, updateNode } from "@/api/graphvis/node"
    import { listLink,listAllLink, getLink, delLink, addLink, updateLink } from "@/api/graphvis/link"
    export default {
        components: {
            VisGraph,
            LayoutFactory
        },
        data () {
            return {
                // visGraph实例
                visGraph: null,
                // visGraph设置信息
                config,
                // visGraph创建知识联系的节点集和联系集
                graphData: {
                    nodes: [],
                    links: []
                },
                // 双击选中的节点信息
                nodeInfo: {
                    properties: {}
                },
                // 双击选中的联系信息
                linkInfo: {},
                // 控制编辑节点对话框的显示
                editNodeDialog: false,
                // 节点在编辑对话框内的信息
                editNode: {
                    id: '',
                    classId: '',
                    knowledgeName: '',
                    knowledgeContent: '',
                    size: '',
                    knowledgeTag: '',
                    color: ''
                },
                // 知识分类列表
                categories: [],
                // 判断当前是否进行联系知识操作(还存储父节点的ID)
                relativeNodeId: '',
                // 添加知识表单
                addNodeForm: {
                    classId: '',
                    knowledgeName: '',
                    knowledgeContent: '',
                    size: '',
                    color: 'rgb(0, 0, 0)'
                },
                // 添加知识对话框是否开启
                addNodeDialog: false,
                // 目前所在分类的Id
                currentCateId: 0,
                // 是否显示知识详细信息
                nodeContentDialog: false,
                // 用户已收藏的知识
                collectList: [],
                loading: true
            }
        },
        methods: {
            // 获取所有的知识节点信息
            async getTagsList (id) {
                const {data: res} = await getNode(id)
                this.graphData = {
                    nodes: [],
                    links: []
                }
                res.data.forEach(item => {
                    let node = {properties: {}}
                    node.id = item.nodeId
                    node.label = item.label
                    node.color = item.color
                    node.size = item.size
                    this.graphData.nodes.push(node)
                })
                this.getTagsRelativeList(id)
            },
            // 获取所有的知识联系信息
            async getTagsRelativeList (id) {
                const {data: res} = await getLink(id)
                res.data.forEach(item => {
                    let link = {properties: {}}
                    link.properties.id = item.id
                    link.source = item.fatherId
                    link.target = item.sonId
                    this.graphData.links.push(link)
                })
                if (this.visGraph === null) {
                    this.createCanvas()
                } else {
                    this.refreshCanvas()
                }
            },
            // 创建canvas
            createCanvas () {
                this.visGraph = new VisGraph(document.getElementById('canvasMainId'), this.config)
                this.refreshCanvas()
            },
            // 刷新知识图谱
            refreshCanvas () {
                this.visGraph.clearAll()
                this.visGraph.drawData(this.graphData)
                this.layoutCanvas()
            },
            // 执行布局算法
            layoutCanvas () {
                var layout = new LayoutFactory(this.visGraph.getVisibleData()).createLayout('fastFR')
                layout.initAlgo()
                let i = 0
                while (i++ < 300) {
                    layout.runLayout()
                }
                this.loading = false
            },
            // 显示知识简介
            nodeTags () {
                let string = this.nodeInfo.properties.knowledgeTag.replace(/\|/g, '&nbsp;&nbsp;')
                this.$confirm(string, this.nodeInfo.label, {
                    confirmButtonText: '了解详细',
                    cancelButtonText: '取消',
                    dangerouslyUseHTMLString: true
                }).then(() => {
                    this.nodeContentDialog = true
                }).catch(err => { console.log(err) })
                this.cancel()
            },
            // 显示知识操作栏(鼠标双击节点)
            mouseTwoClicked (event, node) {
                let nodeDialog = document.getElementById('nodeDialogId')
                nodeDialog.style.left = event.clientX + 'px'
                nodeDialog.style.top = event.clientY + 'px'
                nodeDialog.style.display = 'block'
                this.nodeInfo = node
                event.stopPropagation()
            },
            // 关闭知识操作栏
            cancel () {
                let nodeDialog = document.getElementById('nodeDialogId')
                nodeDialog.style.display = 'none'
            },
            // 关闭知识联系操作栏
            cancelLink () {
                let linkDialog = document.getElementById('linkDialogId')
                linkDialog.style.display = 'none'
            },
            // 删除知识操作
            async deleteNodeClick () {
                const {data: res} = await deleteNode(this.nodeInfo.id)
                if (res.code === 200) {
                    let node = this.visGraph.findNode(this.nodeInfo.label)
                    this.visGraph.deleteNode(node)
                    this.visGraph.showAllNode()
                    this.$message.success(res.msg)
                } else {
                    this.$message.error(res.msg)
                }
                this.cancel()
                this.popoverNodeClose()
            },
            // 关闭删除知识的对话框
            popoverNodeClose () {
                this.$refs.popoverNode.doClose()
            },
            // 删除知识联系操作
            async deleteLinkClick () {
                const {data: res} = await deleteLink(this.linkInfo.properties.id)
                if (res.code === 200) {
                    this.visGraph.deleteLink(this.linkInfo)
                    this.visGraph.showAllNode()
                    this.$message.success(res.msg)
                } else {
                    this.$message.error(res.msg)
                }
                this.cancelLink()
                this.popoverLinkClose()
            },
            // 关闭删除知识联系的对话框
            popoverLinkClose () {
                this.$refs.popoverLink.doClose()
            },
            // 获取知识分类列表
            async getCategoriesList () {
                const {data: res} = await getCategoies()
                this.categories = res.data
            },
            // 编辑知识操作
            async editNoded () {
                if (this.editNode.color === null) {
                    this.editNode.color = '0,0,0'
                } else {
                    let color = this.editNode.color
                    color = color.slice(4, color.length - 1)
                    color = color.replace(/\s*/g, '')
                    this.editNode.color = color
                }
                const {data: res} = await updateNode(this.editNode)
                if (res.code === 200) {
                    this.$message.success(res.msg)
                    this.getTagsList(this.currentCateId)
                } else {
                    this.getTagsList(this.currentCateId)
                    this.$message.error(res.msg)
                }
                this.editNodeDialog = false
            },
            // 打开知识编辑对话框
            showEditNodeDialog () {
                this.editNode.id = this.nodeInfo.id
                this.editNode.classId = this.nodeInfo.properties.classId
                this.editNode.knowledgeName = this.nodeInfo.label
                this.editNode.knowledgeContent = this.nodeInfo.properties.knowledgeContent
                this.editNode.size = this.nodeInfo.height
                this.editNode.knowledgeTag = this.nodeInfo.properties.knowledgeTag
                this.editNode.color = 'rgb(' + this.nodeInfo.fillColor.replace(/,/g, ', ') + ')'
                this.editNodeDialog = true
                this.cancel()
            },
            // 开启知识联系操作
            relative () {
                this.visGraph.begainAddLine(this.nodeInfo)
                this.relativeNodeId = this.nodeInfo.id
                this.cancel()
            },
            // 知识联系确认操作(看relativeNodeId是否为空)
            mouseClicked (event, node) {
                if (this.relativeNodeId) {
                    this.nodeRelatived(node.id)
                } else {
                    return false
                }
            },
            // 把知识联系存储到服务端
            async nodeRelatived (id) {
                const {data: res} = await insertRelative({
                    fatherId: this.relativeNodeId,
                    sonId: id
                })
                if (res.code === 200) {
                    this.$message.success(res.msg)
                    this.getTagsList(this.currentCateId)
                } else {
                    this.$message.error(res.msg)
                }
                this.relativeNodeId = ''
            },
            // 打开知识联系操作栏(双击连线)
            mouseTowClickedOnRelative (event, link) {
                let linkDialog = document.getElementById('linkDialogId')
                linkDialog.style.left = event.clientX + 'px'
                linkDialog.style.top = event.clientY + 'px'
                linkDialog.style.display = 'block'
                this.linkInfo = link
            },
            // 关闭知识连接操作
            domMouseTwoClicked () {
                this.relativeNodeId = ''
            },
            // 添加知识操作
            async addNode () {
                if (this.addNodeForm.color === null) {
                    this.addNodeForm.color = '0,0,0'
                } else {
                    let color = this.addNodeForm.color
                    color = color.slice(4, color.length - 1)
                    color = color.replace(/\s*/g, '')
                    this.addNodeForm.color = color
                }
                const {data: res} = await insertNode(this.addNodeForm)
                if (res.code === 200) {
                    this.getTagsList(this.currentCateId)
                    this.$message.success(res.msg)
                } else {
                    this.$message.error(res.msg)
                }
                this.addNodeDialog = false
            },
            // 关闭添加知识对话框清空添加知识表单
            addDialogClose () {
                this.addNodeForm.classId = ''
                this.addNodeForm.knowledgeName = ''
                this.addNodeForm.knowledgeContent = ''
                this.addNodeForm.size = ''
                this.addNodeForm.knowledgeTag = ''
                this.addNodeForm.color = 'rgb(0, 0, 0)'
            },
            // 点击下拉菜单的内容跳转到相应分类的知识图谱
            handleCommand (command) {
                this.currentCateId = command
                this.getTagsList(this.currentCateId)
            },
            // 判断是否登录
            isLogined () {
                if (window.sessionStorage.token) {
                    return true
                } else {
                    return false
                }
            },
            // 判断权限是否足够
            isPower () {
                if (window.sessionStorage.admin === '1') {
                    return true
                } else {
                    return false
                }
            },
            // 收藏知识
            async collect () {
                if (!this.isLogined()) {
                    this.$emit('needLogin')
                    this.cancel()
                    return false
                }
                const {data: res} = await insertLove(this.nodeInfo.id)
                if (res.code === 200) {
                    this.$message.success(res.msg)
                    this.getCollectList()
                    this.cancel()
                } else {
                    this.$message.error(res.msg)
                }
            },
            // 获取知识收藏
            async getCollectList () {
                const {data: res} = await listUserLove()
                if (res.code === 200) {
                    this.collectList = res.data
                } else {
                    this.$message.error(res.msg)
                }
            },
            // 查看节点是否已收藏
            isCollected () {
                let flag = 0
                this.collectList.forEach((item) => {
                    if (item.id === this.nodeInfo.id) {
                        flag = 1
                    }
                })
                if (flag === 0) {
                    return false
                } else {
                    return true
                }
            }
        },
        created () {
            this.getCategoriesList()
            this.config.node.onClick = this.mouseClicked
            this.config.node.ondblClick = this.mouseTwoClicked
            this.config.node.onMouseDown = function (event, node) {
                event.stopPropagation()
            }
            if (this.isPower()) {
                this.config.link.ondblClick = this.mouseTowClickedOnRelative
            }
            if (this.$route.params.classId) {
                this.currentCateId = this.$route.params.classId
            }
            this.getTagsList(this.currentCateId)
            this.getCategoriesList()
            if (this.isLogined()) {
                this.getCollectList()
            }
        }
    }
</script>

<style scoped>
  /* 整个组件的根组件样式 */
  .canvasMain {
    height: 98%;
    margin: 0;
    padding: 0;
  }
  /* 节点操作栏样式 */
  .nodeDialog {
    position: absolute;
    width: 80px;
    z-index: 5;
    display: none;
    border-radius: 10px;
    overflow: hidden;
    background: white;
  }
  .nodeDialog button {
    display: block;
    width: 80px;
    background: white;
    border: none;
    margin: 5px 2px;
  }
  .nodeDialog button:hover {
    background: skyblue;
  }
  .nodeDialog button:focus {
    outline:0;
  }
  /* 节点联系操作栏样式 */
  .linkDialog {
    position: absolute;
    width: 80px;
    z-index: 5;
    display: none;
    border-radius: 10px;
    overflow: hidden;
    background: white;
  }
  .linkDialog button {
    display: block;
    width: 80px;
    background: white;
    border: none;
    margin: 5px 2px;
  }
  .linkDialog button:hover {
    background: skyblue;
  }
  .linkDialog button:focus {
    outline:0;
  }
  /* 添加节点按钮样式 */
  .addNode {
    position: absolute;
    left: 210px;
    top: 70px;
    width: 70px;
    z-index: 5;
  }
  .content {
    min-height: 300px;
    max-height: 300px;
    overflow: scroll;
  }
  /* 禁用按钮 */
  .notButton {
    cursor: no-drop
  }
  .notButton:hover {
    background: none !important;
  }
</style>
